﻿using WCS.Entity;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using WcsApi.Models;
using WCSApi;
using WcsTask;
using WcsTask.DevCommTaks;
using API.SqlSugar;
using System.Reflection;
using WebApi;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using System.Configuration;
using static WcsAip.Controllers.PDAController;
using WCS.Controls.RunLog;

namespace WcsApi.Controllers
{
    /// <summary>
    /// 任务控制器
    /// </summary>
    [Route("/push/[action]")]
    [ApiExplorerSettings(GroupName = "2")]
    [ApiController]
    public class AGVController : Controller
    {
        public IConfiguration Configuration { get; }

        List<string> pos = new List<string>();

        static SqlSugarDapper _sqlSugarDapper = SqlSugarDapper.GetDbContext();

        public AGVController(MyDbContext commonDbContext, IConfiguration configuration)
        {
            Configuration = configuration;

            pos = configuration.GetConnectionString("Position").Split(',').ToList();
        }

        /// <summary>
        /// 获取物料信息
        /// </summary>
        /// <param name="aGVNunmber"></param>
        /// <returns></returns>
        [HttpGet]
        public Result<PalletToMaterialPDA> GetMaterialInfo()
        {
            try
            {
                var pallet = _sqlSugarDapper.DB.Queryable<PalletToMaterialPDA>().ToList();

                var result = new Result { code = 0 };

                Result<PalletToMaterialPDA>.success(pallet);

                _sqlSugarDapper.DB.Insertable(new ApiLogs(
                    $"{MethodBase.GetCurrentMethod().Name}  获取物料信息",
                    JsonConvert.SerializeObject(result),
                    JsonConvert.SerializeObject("")
                    )).ExecuteCommand();

                return Result<PalletToMaterialPDA>.success(pallet);
            }
            catch (Exception ex)
            {
                var result = new Result { code = 1 };
                _sqlSugarDapper.DB.Insertable(new ApiLogs(
                    $"{MethodBase.GetCurrentMethod().Name}    (获取物料信息)出现异常",
                    JsonConvert.SerializeObject(""),
                    JsonConvert.SerializeObject(result)
                )).ExecuteCommand();

                return null;
            }
        }

        /// <summary>
        /// 获取设备当前生产的物料信息
        /// </summary>
        /// <param name="aGVNunmber"></param>
        /// <returns></returns>
        [HttpGet]
        public string GetDevMaterialInfo(string devCode)
        {
            try
            {
                var plcStation = _sqlSugarDapper.DB.Queryable<WcsDevStation>().Where(w => w.Station_Plc_No == devCode).First();

                _sqlSugarDapper.DB.Insertable(new ApiLogs(
                    $"{MethodBase.GetCurrentMethod().Name}  获取物料信息",
                    JsonConvert.SerializeObject(plcStation),
                    JsonConvert.SerializeObject("")
                    )).ExecuteCommand();

                return plcStation.ProductionMaterials;
            }
            catch (Exception ex)
            {
                _sqlSugarDapper.DB.Insertable(new ApiLogs(
                    $"{MethodBase.GetCurrentMethod().Name}    (获取物料信息)出现异常",
                    JsonConvert.SerializeObject(""),
                    JsonConvert.SerializeObject(devCode)
                )).ExecuteCommand();

                return null;
            }
        }

        /// <summary>
        /// 修改生产信息
        /// </summary>
        /// <param name="aGVNunmber"></param>
        /// <returns></returns>
        [HttpPost]
        public Result UpdatProductionInfo(UpdatProductionInfo updatProductionInfo)
        {
            try
            {
                var plcStation = _sqlSugarDapper.DB.Queryable<WcsDevStation>().Where(w => w.Station_Plc_No == updatProductionInfo.dev).First();

                _sqlSugarDapper.DB.Updateable<WcsDevStation>()
                    .SetColumns(s => s.ProductionMaterials == updatProductionInfo.mal)
                    .Where(s => s.Station_Plc_No == updatProductionInfo.dev).ExecuteCommand();

                // 判断当前砂芯的小车托盘是否和产品需要的的托盘一致
                if (plcStation.ProductionMaterials != updatProductionInfo.mal)
                {
                    //把小车拉走 并换上需要的托盘
                    AGVTask._agvTask.CarIn(plcStation.Station_Plc_No, updatProductionInfo.mal);
                    //不继续生产就把砂芯缓存的入库
                    var station = (Convert.ToInt32(plcStation.Station_Plc_No) + 4).ToString();
                    AGVTask._agvTask.CarIn(station, updatProductionInfo.mal);
                }

                var result = new Result { code = 0 };

                _sqlSugarDapper.DB.Insertable(new ApiLogs(
                    $"{MethodBase.GetCurrentMethod().Name}  站台呼叫",
                    JsonConvert.SerializeObject(result),
                    JsonConvert.SerializeObject(updatProductionInfo)
                    )).ExecuteCommand();

                return result;
            }
            catch (Exception ex)
            {
                var result = new Result { code = 1 };
                _sqlSugarDapper.DB.Insertable(new ApiLogs(
                    $"{MethodBase.GetCurrentMethod().Name}    (站台呼叫)出现异常",
                    JsonConvert.SerializeObject(updatProductionInfo),
                    JsonConvert.SerializeObject(result)
                )).ExecuteCommand();

                return result;
            }
        }


        /// <summary>
        /// 站台呼叫
        /// </summary>
        /// <param name="aGVNunmber"></param>
        /// <returns></returns>
        [HttpPost]
        public Result CallMaterial(CallMaterial callMaterial)
        {
            try
            {
                var result = new Result();
                string mes = "";
                var matericalcode = _sqlSugarDapper.DB.Queryable<PalletToMaterial>()
                     .Where(w => w.MaterialType == callMaterial.MaterialType)
                     .First();

                var count = _sqlSugarDapper.DB.Queryable<WarehouseInfo>()
                    .Where(w => w.barCode.Contains($"{matericalcode.PalletCode}"))
                    .ToList().Count();

                if (callMaterial.isSupply == 0)
                {
                    if (count < 2 || count == 0)
                    {
                        result = new Result { code = 2, message = $"{callMaterial.MaterialType}可用砂芯数量不足" };

                        _sqlSugarDapper.DB.Insertable(new ApiLogs(
                            $"{MethodBase.GetCurrentMethod().Name}  站台呼叫",
                            JsonConvert.SerializeObject(result),
                            JsonConvert.SerializeObject(callMaterial)
                            )).ExecuteCommand();

                        return result;
                    }

                    var info = GetWarehouseByMaterialTypeOut(1, callMaterial.MaterialType, ref mes);
                    if (info == null)
                    {
                        result = new Result { code = 1, message = $"{callMaterial.MaterialType}在库时间未满2小时" };

                        _sqlSugarDapper.DB.Insertable(new ApiLogs(
                            $"{MethodBase.GetCurrentMethod().Name}  站台呼叫",
                            JsonConvert.SerializeObject(result),
                            JsonConvert.SerializeObject(callMaterial)
                            )).ExecuteCommand();

                        return result;
                    }
                }
                switch (callMaterial.CallStation)
                {
                    case "D1":
                        callMaterial.CallStation = "3001";
                        break;
                    case "D2":
                        callMaterial.CallStation = "3002";
                        break;
                    case "D3":
                        callMaterial.CallStation = "3003";
                        break;
                    case "D4":
                        callMaterial.CallStation = "3004";
                        break;
                    case "D5":
                        callMaterial.CallStation = "3005";
                        break;
                    case "C1":
                        callMaterial.CallStation = "3006";
                        break;
                    case "C2":
                        callMaterial.CallStation = "3007";
                        break;
                    case "C3":
                        callMaterial.CallStation = "3008";
                        break;
                    case "C4":
                        callMaterial.CallStation = "3009";
                        break;
                    case "C5":
                        callMaterial.CallStation = "3010";
                        break;
                    default:
                        break;
                }

                result = new Result { code = 0, message = $"{callMaterial.MaterialType}叫料成功" };

                CallMaterial callMaterial1 = new CallMaterial()
                {
                    CallStation = callMaterial.CallStation,
                    isSupply = callMaterial.isSupply,
                    SupplyNum = callMaterial.SupplyNum,
                    MaterialType = callMaterial.MaterialType,
                };

                _sqlSugarDapper.DB.Insertable(callMaterial1)
                    .ExecuteCommand();

                _sqlSugarDapper.DB.Insertable(new ApiLogs(
                    $"{MethodBase.GetCurrentMethod().Name}  站台呼叫",
                    JsonConvert.SerializeObject(result),
                    JsonConvert.SerializeObject(callMaterial)
                    )).ExecuteCommand();

                return result;
            }
            catch (Exception ex)
            {
                var result = new Result { code = 1 };
                _sqlSugarDapper.DB.Insertable(new ApiLogs(
                    $"{MethodBase.GetCurrentMethod().Name}    (站台呼叫)出现异常",
                    JsonConvert.SerializeObject(callMaterial),
                    JsonConvert.SerializeObject(result)
                )).ExecuteCommand();

                return result;
            }
        }

        /// <summary>
        /// AGV编号上传WCS
        /// </summary>
        /// <param name="aGVNunmber"></param>
        /// <returns></returns>
        [HttpPost]
        public Result<object> ResponseTaskAGVNo(AGVNunmber aGVNunmber)
        {
            try
            {
                _sqlSugarDapper.DB.Updateable<WcsTaskAGV>()
                    .Where(p => p.Sub_TaskCode == aGVNunmber.SubTaskCode)
                    .ExecuteCommand();

                var result = Result<object>.success();

                _sqlSugarDapper.DB.Insertable(new ApiLogs(
                    $"{MethodBase.GetCurrentMethod().Name}  AGV小车编号",
                    JsonConvert.SerializeObject(result),
                    JsonConvert.SerializeObject(aGVNunmber)
                    )).ExecuteCommand();

                return result;
            }
            catch (Exception ex)
            {
                var result = Result<object>.error(ex.Message);
                _sqlSugarDapper.DB.Insertable(new ApiLogs(
                    "ResponseTaskAGVNo    AGV(小车编号上传)出现异常",
                    JsonConvert.SerializeObject(aGVNunmber),
                    JsonConvert.SerializeObject(result)
                )).ExecuteCommand();

                return result;
            }
        }

        /// <summary>
        /// PDA下发任务到缓存区
        /// </summary>
        /// <param name="pDAResponse"></param>
        /// <returns></returns>
        [HttpPost]
        public Result<object> ResponseTaskPAD(CallMaterial callMaterial)
        {
            try
            {
                var station = _sqlSugarDapper.DB.Queryable<CallMaterial>().ToList().Find(f => f.CallStation == callMaterial.CallStation);
                if (station != null)
                {
                    return Result<object>.error("该站台已有申请记录，不能重复申请");
                }

                _sqlSugarDapper.DB.Insertable(callMaterial).ExecuteCommand();

                var result = Result<object>.success();
                // 记录接口请求返回信息
                _sqlSugarDapper.DB.Insertable(new ApiLogs(
                    $"{MethodBase.GetCurrentMethod().Name}       (PDA下发任务)",
                    JsonConvert.SerializeObject(callMaterial),
                    JsonConvert.SerializeObject(result)
                    )).ExecuteCommand();

                return result;
            }
            catch (Exception ex)
            {
                var result = Result<object>.error(ex.Message);
                _sqlSugarDapper.DB.Insertable(new ApiLogs(
                    $"{MethodBase.GetCurrentMethod().Name}       (PDA下发任务)出现异常",
                    JsonConvert.SerializeObject(callMaterial),
                    JsonConvert.SerializeObject(result)
                )).ExecuteCommand();

                return result;
            }
        }

        /// <summary>
        /// 回传任务链信息
        /// </summary>
        /// <param name="pDAResponse"></param>
        /// <returns></returns>
        [HttpPost]
        public Receive taskInfo(AGVRes aGVRes)
        {
            try
            {
                /*
                 AGV上报任务完成 首先判断当前任务是否是申请进入的站台
                 再判断当前站台是否是PLC交互站台
                 */
                var receive = new Receive
                {
                    receive = "1"
                };

                var subTask = JsonConvert.DeserializeObject<SubTask>(aGVRes.taskPo?.extend);

                if (subTask == null)
                {
                    return receive;
                }
                //任务完成
                if (aGVRes.taskPo.status == 2)
                {
                    _sqlSugarDapper.DB.Updateable<WcsTaskAGV>()
                        .SetColumns(s => s.AGVTaskID == aGVRes.taskChainPo.id)
                        .Where(w => w.Sub_TaskCode == subTask.sub).ExecuteCommand();
                    if (pos.Contains(aGVRes.taskPo.endPointCode))
                    {
                        _sqlSugarDapper.DB.Updateable<WcsTaskAGV>()
                            .SetColumns(s => s.ReceiveInteractiveState == 8)
                            .Where(w => w.Sub_TaskCode == subTask.sub).ExecuteCommand();
                    }
                    else
                    {
                        if (aGVRes.taskPo.endPointCode == "A001" || aGVRes.taskPo.endPointCode == "A007" ||
                            aGVRes.taskPo.endPointCode == "B001" || aGVRes.taskPo.endPointCode == "B007")
                        {
                            _sqlSugarDapper.DB.Updateable<WcsTaskAGV>()
                                .SetColumns(s => s.InteractiveState == 26)
                                .SetColumns(s => s.ReceiveInteractiveState == 28)
                                .Where(w => w.Sub_TaskCode == subTask.sub).ExecuteCommand();
                        }
                        else
                        {
                            _sqlSugarDapper.DB.Updateable<WcsTaskAGV>()
                                .SetColumns(s => s.ReceiveInteractiveState == 50)
                                .Where(w => w.Sub_TaskCode == subTask.sub).ExecuteCommand();
                        }
                    }
                }

                // 记录接口请求返回信息
                _sqlSugarDapper.DB.Insertable(new ApiLogs(
                    $"{MethodBase.GetCurrentMethod().Name}       (回传任务链信息)",
                    JsonConvert.SerializeObject(aGVRes),
                    JsonConvert.SerializeObject("1")
                    )).ExecuteCommand();

                return receive;
            }
            catch (Exception ex)
            {
                var result = Result<object>.error(ex.Message);
                _sqlSugarDapper.DB.Insertable(new ApiLogs(
                    $"{MethodBase.GetCurrentMethod().Name}       (回传任务链信息)出现异常",
                    JsonConvert.SerializeObject(aGVRes.taskChainPo),
                    JsonConvert.SerializeObject(result)
                )).ExecuteCommand();

                return null;
            }
        }

        /// <summary>
        /// 根据物料类型查找所在仓库
        /// </summary>
        /// <param name="material"></param>
        /// <returns></returns>
        public static List<WarehouseInfo> GetWarehouseByMaterialTypeOut(int isFullMaterial, string materialType, ref string mes)
        {
            List<WarehouseInfo> strings = new List<WarehouseInfo>();

            var warehouseListGroup = _sqlSugarDapper.DB.SqlQueryable<WarehouseInfo>($@"SELECT * FROM WCS_WarehouseInfo WHERE ID IN (  SELECT   ID  FROM   WCS_Warehouse
                        WHERE   IsFullMaterial = {isFullMaterial}  AND MaterialType = '{materialType}' )
                     ORDER BY [index]").ToList().GroupBy(g => g.ID).ToList();

            foreach (var warehouses in warehouseListGroup)
            {
                var Warehouse = _sqlSugarDapper.DB.Queryable<Warehouse>().Where(w => w.ID == warehouses.Key).First();

                var warehouseInfos = _sqlSugarDapper.DB.SqlQueryable<WarehouseInfo>("SELECT *,DATEDIFF(hh, CreateTime,GETDATE()) as dataIff from WCS_WarehouseInfo").Where(w => w.ID == Warehouse.ID).OrderBy(o => o.index).ToList();

                foreach (var warehouseInfo in warehouseInfos)
                {
                    if (warehouseInfo.dataIff < 2 || warehouseInfo.dataIff > 168)
                    {
                        continue;
                    }
                    strings.Add(warehouseInfo);
                    //判断PLC第二个有没有货
                    if (strings.Count >= 2)
                    {
                        return strings;
                    }
                }
            }
            return null;
        }
    }


    public class UpdatProductionInfo
    {
        /// <summary>
        /// 站台号
        /// </summary>
        public string dev { get; set; }

        /// <summary>
        /// 物料类型
        /// </summary>
        public string mal { get; set; }
    }

    public class Receive
    {
        public string receive { get; set; }
    }

    public class SubTask
    {
        public string sub { get; set; }
    }

    public class AGVRes
    {
        public TaskChainPo taskChainPo { get; set; }

        /// <summary>
        /// 任务链ID
        /// </summary>
        public TaskPo taskPo { get; set; }
    }

    public class TaskChainPo
    {
        /// <summary>
        /// 任务链ID
        /// </summary>
        public int id { get; set; }

        /// <summary>
        /// 区域ID
        /// </summary>
        public int areaId { get; set; }

        /// <summary>
        /// 创建时间
        /// </summary>
        //public DateTime? createTime { get; set; }

        /// <summary>
        /// 车辆ID
        /// </summary>
        public int amrId { get; set; }

        /// <summary>
        /// 任务链状态;
        ///0-未执行;
        ///1-正在执行;
        ///2-结束;
        ///3-取消;
        ///4-执行异常
        /// </summary>
        public int status { get; set; }
    }

    public class TaskPo
    {
        /// <summary>
        /// 子任务ID
        /// </summary>
        public long id { get; set; }

        /// <summary>
        /// 动作类型
        /// </summary>
        public string taskType { get; set; }

        /// <summary>
        /// 目标点编号
        /// </summary>
        public string endPointCode { get; set; }

        /// <summary>
        /// 地图ID
        /// </summary>
        public int mapId { get; set; }

        /// <summary>
        /// 子任务状态;
        ///0-未执行;
        ///1-正在执行;
        ///2-结束;
        ///3-取消;
        ///4-执行异常;
        ///5-跳过
        ///6-暂停
        /// </summary>
        public int status { get; set; }

        /// <summary>
        /// 子任务开始时间
        /// </summary>
        //public DateTime? startTime { get; set; }

        ///// <summary>
        ///// 子任务结束时间
        ///// </summary>
        //public DateTime? finishTime { get; set; }

        /// <summary>
        /// 上下料属性 0-上料 1-下料
        /// </summary>
        public int loading { get; set; }

        /// <summary>
        /// 任务拓展字段
        /// </summary>
        public string extend { get; set; }
    }
}